home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / olecon~1 / framewrk / proppage.cpp < prev    next >
Text File  |  1995-11-25  |  20KB  |  746 lines

  1. //=--------------------------------------------------------------------------=
  2. // PropertyPages.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright  1995  Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implementation of CPropertyPage object.
  13. //
  14. #include "IPServer.H"
  15. #include "PropPage.H"
  16. #include "Util.H"
  17. #include "Globals.H"
  18.  
  19. // for ASSERT and FAIL
  20. //
  21. SZTHISFILE
  22.  
  23. // this variable is used to pass the pointer to the object to the hwnd.
  24. //
  25. static CPropertyPage *s_pLastPageCreated;
  26.  
  27. //=--------------------------------------------------------------------------=
  28. // CPropertyPage::CPropertyPage
  29. //=--------------------------------------------------------------------------=
  30. // constructor.
  31. //
  32. // Parameters:
  33. //    IUnknown *          - [in] controlling unknown
  34. //    int                 - [in] object type.
  35. //
  36. // Notes:
  37. //
  38. #pragma warning(disable:4355)  // using 'this' in constructor
  39. CPropertyPage::CPropertyPage
  40. (
  41.     IUnknown         *pUnkOuter,
  42.     int               iObjectType
  43. )
  44. : CUnknownObject(pUnkOuter, this), m_ObjectType(iObjectType)
  45. {
  46.     // initialize various dudes.
  47.     //
  48.     m_pPropertyPageSite = NULL;
  49.     m_hwnd = NULL;
  50.     m_fDirty = FALSE;
  51.     m_fActivated = FALSE;
  52.     m_cObjects = 0;
  53. }
  54. #pragma warning(default:4355)  // using 'this' in constructor
  55.  
  56.  
  57. //=--------------------------------------------------------------------------=
  58. // CPropertyPage::~CPropertyPage
  59. //=--------------------------------------------------------------------------=
  60. // destructor.
  61. //
  62. // Notes:
  63. //
  64. CPropertyPage::~CPropertyPage()
  65. {
  66.     // clean up our window.
  67.     //
  68.     if (m_hwnd)
  69.         DestroyWindow(m_hwnd);
  70.  
  71.     // release all the objects we're holding on to.
  72.     //
  73.     m_ReleaseAllObjects();
  74.  
  75.     // release the site
  76.     //
  77.     RELEASE_OBJECT(m_pPropertyPageSite);
  78. }
  79.  
  80. //=--------------------------------------------------------------------------=
  81. // CPropertyPage::InternalQueryInterface
  82. //=--------------------------------------------------------------------------=
  83. // we support IPP and IPP2.
  84. //
  85. // Parameters:
  86. //    REFIID        - [in]  interface they want
  87. //    void **       - [out] where they want to put the resulting object ptr.
  88. //
  89. // Output:
  90. //    HRESULT       - S_OK, E_NOINTERFACE
  91. //
  92. // Notes:
  93. //
  94. HRESULT CPropertyPage::InternalQueryInterface
  95. (
  96.     REFIID  riid,
  97.     void  **ppvObjOut
  98. )
  99. {
  100.     IUnknown *pUnk;
  101.  
  102.     *ppvObjOut = NULL;
  103.  
  104.     if (DO_GUIDS_MATCH(IID_IPropertyPage, riid)) {
  105.         pUnk = (IUnknown *)this;
  106.     } else if (DO_GUIDS_MATCH(IID_IPropertyPage2, riid)) {
  107.         pUnk = (IUnknown *)this;
  108.     } else {
  109.         return CUnknownObject::InternalQueryInterface(riid, ppvObjOut);
  110.     }
  111.  
  112.     pUnk->AddRef();
  113.     *ppvObjOut = (void *)pUnk;
  114.     return S_OK;
  115. }
  116.  
  117. //=--------------------------------------------------------------------------=
  118. // CPropertyPage::SetPageSite    [IPropertyPage]
  119. //=--------------------------------------------------------------------------=
  120. // the initialization function for a property page through which the page
  121. // receives an IPropertyPageSite pointer.
  122. //
  123. // Parameters:
  124. //    IPropertyPageSite *        - [in] new site.
  125. //
  126. // Output:
  127. //    HRESULT
  128. //
  129. // Notes;
  130. //
  131. STDMETHODIMP CPropertyPage::SetPageSite
  132. (
  133.     IPropertyPageSite *pPropertyPageSite
  134. )
  135. {
  136.     RELEASE_OBJECT(m_pPropertyPageSite);
  137.     m_pPropertyPageSite = pPropertyPageSite;
  138.     ADDREF_OBJECT(pPropertyPageSite);
  139.  
  140.     return S_OK;
  141. }
  142.  
  143. //=--------------------------------------------------------------------------=
  144. // CPropertyPage::Activate    [IPropertyPage]
  145. //=--------------------------------------------------------------------------=
  146. // instructs the page to create it's display window as a child of hwndparent
  147. // and to position it according to prc.
  148. //
  149. // Parameters:
  150. //    HWND                - [in]  parent window
  151. //    LPCRECT             - [in]  where to position ourselves
  152. //    BOOL                - [in]  whether we're modal or not.
  153. //
  154. // Output:
  155. //    HRESULT
  156. //
  157. // Notes:
  158. //
  159. STDMETHODIMP CPropertyPage::Activate
  160. (
  161.     HWND    hwndParent,
  162.     LPCRECT prcBounds,
  163.     BOOL    fModal
  164. )
  165. {
  166.     HRESULT hr;
  167.  
  168.     // first make sure the dialog window is loaded and created.
  169.     //
  170.     hr = m_EnsureLoaded();
  171.     RETURN_ON_FAILURE(hr);
  172.  
  173.     // set our parent window if we haven't done so yet.
  174.     //
  175.     if (!m_fActivated) {
  176.         SetParent(m_hwnd, hwndParent);
  177.         m_fActivated = TRUE;
  178.     }
  179.  
  180.     // now move ourselves to where we're told to be and show ourselves
  181.     //
  182.     Move(prcBounds);
  183.     ShowWindow(m_hwnd, SW_SHOW);
  184.  
  185.     return S_OK;
  186. }
  187.  
  188. //=--------------------------------------------------------------------------=
  189. // CPropertyPage::Deactivate    [IPropertyPage]
  190. //=--------------------------------------------------------------------------=
  191. // instructs the page to destroy the window created in activate
  192. //
  193. // Output:
  194. //    HRESULT
  195. //
  196. // Notes:
  197. //
  198. STDMETHODIMP CPropertyPage::Deactivate
  199. (
  200.     void
  201. )
  202. {
  203.     // blow away yon window.
  204.     //
  205.     if (m_hwnd)
  206.         DestroyWindow(m_hwnd);
  207.     m_hwnd = NULL;
  208.     m_fActivated = FALSE;
  209.  
  210.     return S_OK;
  211. }
  212.  
  213. //=--------------------------------------------------------------------------=
  214. // CPropertyPage::GetPageInfo    [IPropertyPage]
  215. //=--------------------------------------------------------------------------=
  216. // asks the page to fill a PROPPAGEINFO structure
  217. //
  218. // Parameters:
  219. //    PROPPAGEINFO *    - [out] where to put info.
  220. //
  221. // Output:
  222. //    HRESULT
  223. //
  224. // Notes:
  225. //
  226. STDMETHODIMP CPropertyPage::GetPageInfo
  227. (
  228.     PROPPAGEINFO *pPropPageInfo
  229. )
  230. {
  231.     RECT rect;
  232.  
  233.     CHECK_POINTER(pPropPageInfo);
  234.  
  235.     m_EnsureLoaded();
  236.  
  237.     // clear it out first.
  238.     //
  239.     memset(pPropPageInfo, 0, sizeof(PROPPAGEINFO));
  240.  
  241.     pPropPageInfo->pszTitle = OLESTRFROMRESID(TITLEIDOFPROPPAGE(m_ObjectType));
  242.     pPropPageInfo->pszDocString = OLESTRFROMRESID(DOCSTRINGIDOFPROPPAGE(m_ObjectType));
  243.     pPropPageInfo->pszHelpFile = OLESTRFROMANSI(HELPFILEOFPROPPAGE(m_ObjectType));
  244.     pPropPageInfo->dwHelpContext = HELPCONTEXTOFPROPPAGE(m_ObjectType);
  245.  
  246.     if (!(pPropPageInfo->pszTitle && pPropPageInfo->pszDocString && pPropPageInfo->pszHelpFile))
  247.         goto CleanUp;
  248.  
  249.     // if we've got a window yet, go and set up the size information they want.
  250.     //
  251.     if (m_hwnd) {
  252.         GetWindowRect(m_hwnd, &rect);
  253.  
  254.         pPropPageInfo->size.cx = rect.right - rect.left;
  255.         pPropPageInfo->size.cy = rect.bottom - rect.top;
  256.     }
  257.  
  258.     return S_OK;
  259.  
  260.   CleanUp:
  261.     if (pPropPageInfo->pszDocString) CoTaskMemFree(pPropPageInfo->pszDocString);
  262.     if (pPropPageInfo->pszHelpFile) CoTaskMemFree(pPropPageInfo->pszHelpFile);
  263.     if (pPropPageInfo->pszTitle) CoTaskMemFree(pPropPageInfo->pszTitle);
  264.  
  265.     return E_OUTOFMEMORY;
  266. }
  267.  
  268. //=--------------------------------------------------------------------------=
  269. // CPropertyPage::SetObjects    [IPropertyPage]
  270. //=--------------------------------------------------------------------------=
  271. // provides the page with the objects being affected by the changes.
  272. //
  273. // Parameters:
  274. //    ULONG            - [in] count of objects.
  275. //    IUnknown **      - [in] objects.
  276. //
  277. // Output:
  278. //    HRESULT
  279. //
  280. // Notes:
  281. //
  282. STDMETHODIMP CPropertyPage::SetObjects
  283. (
  284.     ULONG      cObjects,
  285.     IUnknown **ppUnkObjects
  286. )
  287. {
  288.     HRESULT hr;
  289.     ULONG   x;
  290.  
  291.     // free up all the old objects first.
  292.     //
  293.     m_ReleaseAllObjects();
  294.  
  295.     if (!cObjects)
  296.         return S_OK;
  297.  
  298.     // now go and set up the new ones.
  299.     //
  300.     m_ppUnkObjects = (IUnknown **)HeapAlloc(g_hHeap, 0, cObjects * sizeof(IUnknown *));
  301.     RETURN_ON_NULLALLOC(m_ppUnkObjects);
  302.  
  303.     // loop through and copy over all the objects.
  304.     //
  305.     for (x = 0; x < cObjects; x++) {
  306.         m_ppUnkObjects[x] = ppUnkObjects[x];
  307.         ADDREF_OBJECT(m_ppUnkObjects[x]);
  308.     }
  309.  
  310.     // go and tell the object that there are new objects
  311.     //
  312.     hr = S_OK;
  313.     m_cObjects = cObjects;
  314.     // if we've got a window, go and notify it that we've got new objects.
  315.     //
  316.     if (m_hwnd)
  317.         SendMessage(m_hwnd, PPM_NEWOBJECTS, 0, (LPARAM)&hr);
  318.     if (SUCCEEDED(hr)) m_fDirty = FALSE;
  319.  
  320.     return hr;
  321. }
  322.  
  323. //=--------------------------------------------------------------------------=
  324. // CPropertyPage::Show    [IPropertyPage]
  325. //=--------------------------------------------------------------------------=
  326. // asks the page to show or hide its window
  327. //
  328. // Parameters:
  329. //    UINT             - [in] whether to show or hide
  330. //
  331. // Output:
  332. //    HRESULT
  333. //
  334. // Notes:
  335. //
  336. STDMETHODIMP CPropertyPage::Show
  337. (
  338.     UINT nCmdShow
  339. )
  340. {
  341.     if (m_hwnd)
  342.         ShowWindow(m_hwnd, nCmdShow);
  343.     else
  344.         return E_UNEXPECTED;
  345.  
  346.     return S_OK;
  347. }
  348.  
  349. //=--------------------------------------------------------------------------=
  350. // CPropertyPage::Move    [IPropertyPage]
  351. //=--------------------------------------------------------------------------=
  352. // asks the page to relocate and resize itself to a position other than what
  353. // was specified through Activate
  354. //
  355. // Parameters:
  356. //    LPCRECT        - [in] new position and size
  357. //
  358. // Output:
  359. //    HRESULT
  360. //
  361. // Notes:
  362. //
  363. STDMETHODIMP CPropertyPage::Move
  364. (
  365.     LPCRECT prcBounds
  366. )
  367. {
  368.     // do what they sez
  369.     //
  370.     if (m_hwnd)
  371.         SetWindowPos(m_hwnd, NULL, prcBounds->top, prcBounds->left,
  372.                      prcBounds->right - prcBounds->left,
  373.                      prcBounds->bottom - prcBounds->top,
  374.                      SWP_NOZORDER);
  375.     else
  376.         return E_UNEXPECTED;
  377.  
  378.     return S_OK;
  379. }
  380.  
  381. //=--------------------------------------------------------------------------=
  382. // CPropertyPage::IsPageDirty    [IPropertyPage]
  383. //=--------------------------------------------------------------------------=
  384. // asks the page whether it has changed its state
  385. //
  386. // Output
  387. //    S_OK            - yep
  388. //    S_FALSE         - nope
  389. //
  390. // Notes:
  391. //
  392. STDMETHODIMP CPropertyPage::IsPageDirty
  393. (
  394.     void
  395. )
  396. {
  397.     return m_fDirty ? S_OK : S_FALSE;
  398. }
  399.  
  400. //=--------------------------------------------------------------------------=
  401. // CPropertyPage::Apply    [IPropertyPage]
  402. //=--------------------------------------------------------------------------=
  403. // instructs the page to send its changes to all the objects passed through
  404. // SetObjects()
  405. //
  406. // Output:
  407. //    HRESULT
  408. //
  409. // Notes:
  410. //
  411. STDMETHODIMP CPropertyPage::Apply
  412. (
  413.     void
  414. )
  415. {
  416.     HRESULT hr = S_OK;
  417.  
  418.     if (m_hwnd) {
  419.         SendMessage(m_hwnd, PPM_APPLY, 0, (LPARAM)&hr);
  420.         RETURN_ON_FAILURE(hr);
  421.  
  422.         if (m_fDirty) {
  423.             m_fDirty = FALSE;
  424.             if (m_pPropertyPageSite)
  425.                 m_pPropertyPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
  426.         }
  427.     } else
  428.         return E_UNEXPECTED;
  429.  
  430.     return S_OK;
  431. }
  432.  
  433. //=--------------------------------------------------------------------------=
  434. // CPropertyPage::Help    [IPropertyPage]
  435. //=--------------------------------------------------------------------------=
  436. // instructs the page that the help button was clicked.
  437. //
  438. // Parameters:
  439. //    LPCOLESTR        - [in] help directory
  440. //
  441. // Output:
  442. //    HRESULT
  443. //
  444. // Notes:
  445. //
  446. STDMETHODIMP CPropertyPage::Help
  447. (
  448.     LPCOLESTR pszHelpDir
  449. )
  450. {
  451.     BOOL f;
  452.  
  453.     ASSERT(m_hwnd, "How can somebody have clicked Help, but we don't have an hwnd?");
  454.  
  455.     // oblige them and show the help.
  456.     //
  457.     MAKE_ANSIPTR_FROMWIDE(psz, pszHelpDir);
  458.     f = WinHelp(m_hwnd, psz, HELP_CONTEXT, HELPCONTEXTOFPROPPAGE(m_ObjectType));
  459.  
  460.     return f ? S_OK : E_FAIL;
  461. }
  462.  
  463. //=--------------------------------------------------------------------------=
  464. // CPropertyPage::TranslateAccelerator    [IPropertyPage]
  465. //=--------------------------------------------------------------------------=
  466. // informs the page of keyboard events, allowing it to implement it's own
  467. // keyboard interface.
  468. //
  469. // Parameters:
  470. //    LPMSG            - [in] message that triggered this
  471. //
  472. // Output:
  473. //    HRESULT
  474. //
  475. // Notes:
  476. //
  477. STDMETHODIMP CPropertyPage::TranslateAccelerator
  478. (
  479.     LPMSG pmsg
  480. )
  481. {
  482.     ASSERT(m_hwnd, "How can we geta  TranslateAccelerator call if we're not visible?");
  483.  
  484.     // just pass this message on to the dialog proc and see if they want it.
  485.     //
  486.     return IsDialogMessage(m_hwnd, pmsg) ? S_OK : S_FALSE;
  487. }
  488.  
  489. //=--------------------------------------------------------------------------=
  490. // CPropertyPage::EditProperty    [IPropertyPage2]
  491. //=--------------------------------------------------------------------------=
  492. // instructs the page to set the focus to the property matching the dispid.
  493. //
  494. // Parameters:
  495. //    DISPID            - [in] dispid of property to set focus to.
  496. //
  497. // Output:
  498. //    HRESULT
  499. //
  500. // Notes:
  501. //
  502. STDMETHODIMP CPropertyPage::EditProperty
  503. (
  504.     DISPID dispid
  505. )
  506. {
  507.     HRESULT hr = E_NOTIMPL;
  508.  
  509.     // send the message on to the control, and see what they want to do with it.
  510.     //
  511.     SendMessage(m_hwnd, PPM_EDITPROPERTY, (WPARAM)dispid, (LPARAM)&hr);
  512.  
  513.     return hr;
  514. }
  515.  
  516. //=--------------------------------------------------------------------------=
  517. // CPropertyPage::m_EnsureLoaded
  518. //=--------------------------------------------------------------------------=
  519. // makes sure the dialog is actually loaded
  520. //
  521. // Output:
  522. //    HRESULT
  523. //
  524. // Notes:
  525. //
  526. HRESULT CPropertyPage::m_EnsureLoaded
  527. (
  528.     void
  529. )
  530. {
  531.     HRESULT hr = S_OK;
  532.  
  533.     // duh
  534.     //
  535.     if (m_hwnd)
  536.         return S_OK;
  537.  
  538.     // set up the global variable so that when we're in the dialog proc, we can
  539.     // stuff this in the hwnd
  540.     //
  541.     s_pLastPageCreated = this;
  542.  
  543.     // create the dialog window
  544.     //
  545.     CreateDialog(GetResourceHandle(), TEMPLATENAMEOFPROPPAGE(m_ObjectType), GetParkingWindow(),
  546.                           (DLGPROC)CPropertyPage::PropPageDlgProc);
  547.     ASSERT(m_hwnd, "Couldn't load Dialog Resource!!!");
  548.     if (!m_hwnd)
  549.         return HRESULT_FROM_WIN32(GetLastError());
  550.  
  551.     s_pLastPageCreated = NULL;
  552.  
  553.     // go and notify the window that it should pick up any objects that are
  554.     // available
  555.     //
  556.     SendMessage(m_hwnd, PPM_NEWOBJECTS, 0, (LPARAM)&hr);
  557.  
  558.     return hr;
  559. }
  560.  
  561. //=--------------------------------------------------------------------------=
  562. // CPropertyPage::m_ReleaseAllObjects
  563. //=--------------------------------------------------------------------------=
  564. // releases all the objects that we're working with
  565. //
  566. // Notes:
  567. //
  568. void CPropertyPage::m_ReleaseAllObjects
  569. (
  570.     void
  571. )
  572. {
  573.     UINT x;
  574.  
  575.     if (!m_cObjects)
  576.         return;
  577.  
  578.     // loop through and blow them all away.
  579.     //
  580.     for (x = 0; x < m_cObjects; x++)
  581.         RELEASE_OBJECT(m_ppUnkObjects[x]);
  582.  
  583.     HeapFree(g_hHeap, 0, m_ppUnkObjects);
  584.     m_ppUnkObjects = NULL;
  585. }
  586.  
  587. //=--------------------------------------------------------------------------=
  588. // CPropertyPage::PropPageDlgProc
  589. //=--------------------------------------------------------------------------=
  590. // static global helper dialog proc that gets called before we pass the message
  591. // on to anybody ..
  592. //
  593. // Parameters:
  594. //    - see win32sdk docs on DialogProc
  595. //
  596. // Notes:
  597. //
  598. BOOL CALLBACK CPropertyPage::PropPageDlgProc
  599. (
  600.     HWND    hwnd,
  601.     UINT    msg,
  602.     WPARAM  wParam,
  603.     LPARAM  lParam
  604. )
  605. {
  606.     CPropertyPage *pPropertyPage;
  607.  
  608.     // get the window long, and see if it's been set to the object this hwnd
  609.     // is operating against.  if not, go and set it now.
  610.     //
  611.     pPropertyPage = (CPropertyPage *)GetWindowLong(hwnd, GWL_USERDATA);
  612.     if (!pPropertyPage) {
  613.         SetWindowLong(hwnd, GWL_USERDATA, (LONG)s_pLastPageCreated);
  614.         pPropertyPage = s_pLastPageCreated;
  615.         pPropertyPage->m_hwnd = hwnd;
  616.     }
  617.  
  618.     ASSERT(pPropertyPage, "Uh oh.  Got a window, but no CpropertyPage for it!");
  619.  
  620.     // just call the user dialog proc and see if they want to do anything.
  621.     //
  622.     return pPropertyPage->DialogProc(hwnd, msg, wParam, lParam);
  623. }
  624.  
  625.  
  626. //=--------------------------------------------------------------------------=
  627. // CPropertyPage::FirstControl
  628. //=--------------------------------------------------------------------------=
  629. // returns the first controlish object that we are showing ourselves for.
  630. // returns a cookie that must be passed in for Next ...
  631. //
  632. // Parameters:
  633. //    DWORD *    - [out] cookie to be used for Next
  634. //
  635. // Output:
  636. //    IUnknown *
  637. //
  638. // Notes:
  639. //
  640. IUnknown *CPropertyPage::FirstControl
  641. (
  642.     DWORD *pdwCookie
  643. )
  644. {
  645.     // just use the implementation of NEXT.
  646.     //
  647.     *pdwCookie = 0;
  648.     return NextControl(pdwCookie);
  649. }
  650.  
  651. //=--------------------------------------------------------------------------=
  652. // CPropertyPage::NextControl
  653. //=--------------------------------------------------------------------------=
  654. // returns the next control in the chain of people to work with given a cookie
  655. //
  656. // Parameters:
  657. //    DWORD *            - [in/out] cookie to get next from, and new cookie.
  658. //
  659. // Output:
  660. //    IUnknown *
  661. //
  662. // Notes:
  663. //
  664. IUnknown *CPropertyPage::NextControl
  665. (
  666.     DWORD *pdwCookie
  667. )
  668. {
  669.     UINT      i;
  670.  
  671.     // go looking through all the objects that we've got, and find the
  672.     // first non-null one.
  673.     //
  674.     for (i = *pdwCookie; i < m_cObjects; i++) {
  675.         if (!m_ppUnkObjects[i]) continue;
  676.  
  677.         *pdwCookie = i + 1;                // + 1 so we start at next item next time
  678.         return m_ppUnkObjects[i];
  679.     }
  680.  
  681.     // couldn't find it .
  682.     //
  683.     *pdwCookie = 0xffffffff;
  684.     return NULL;
  685. }
  686.  
  687. //=--------------------------------------------------------------------------=
  688. // CPropertyPage::MakeDirty    [helper, callable]
  689. //=--------------------------------------------------------------------------=
  690. // marks a page as dirty.
  691. //
  692. // Notes:
  693. //
  694. void CPropertyPage::MakeDirty
  695. (
  696.     void
  697. )
  698. {
  699.     m_fDirty = TRUE;
  700.     if (m_pPropertyPageSite)
  701.         m_pPropertyPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY|PROPPAGESTATUS_VALIDATE);
  702. }
  703.  
  704.  
  705. // from Globals.C
  706. //
  707. extern HINSTANCE g_hInstResources;
  708.  
  709.  
  710. //=--------------------------------------------------------------------------=
  711. // CPropertyPage::GetResourceHandle    [helper, callable]
  712. //=--------------------------------------------------------------------------=
  713. // returns current resource handle, based on pagesites ambient LCID.
  714. //
  715. // Output:
  716. //    HINSTANCE
  717. //
  718. // Notes:
  719. //
  720. HINSTANCE CPropertyPage::GetResourceHandle
  721. (
  722.     void
  723. )
  724. {
  725.     if (!g_fSatelliteLocalization)
  726.         return g_hInstance;
  727.  
  728.     // if we've already got it, then there's not all that much to do.
  729.     //
  730.     if (g_hInstResources)
  731.         return g_hInstResources;
  732.  
  733.     // we'll get the ambient localeid from the host, and pass that on to the
  734.     // automation object.
  735.     //
  736.     if (!g_fHaveLocale) {
  737.         if (m_pPropertyPageSite) {
  738.             m_pPropertyPageSite->GetLocaleID(&g_lcidLocale);
  739.             g_fHaveLocale = TRUE;
  740.         }
  741.     }
  742.  
  743.     return ::GetResourceHandle();
  744. }
  745.  
  746.